<?php

/**
 * Created by PhpStorm.
 * User: lian
 * Date: 17/10/27
 * Time: 上午11:56
 */
require_once "Medoo.php";
require_once "Requests/library/Requests.php";
require_once "OneNet/OneNet.php";
require 'pingpp/data/config.php';
require_once 'config.php';
require_once 'config_env.php';
require_once 'Util.class.php';
require_once 'SQL/Database.php';
use Medoo\Medoo;

class msgServer
{
    private $serv;
    private $mDatabase;

    function __construct()
    {
        $this->serv = new Swoole\Server("127.0.0.1", LISTENING_PORT);//创建一个服务
        $this->serv->set(array('task_worker_num' => 10)); //配置task进程的数量
        //必须在onWorkerStart回调中创建redis/mysql连接
        $this->serv->on('workerstart', array($this, 'onWorkerStart'));
        $this->serv->on('receive', array($this, 'onReceive'));//有数据进来的时候执行
        $this->serv->on('task', array($this, 'onTask'));//有任务的时候执行
        $this->serv->on('finish', array($this, 'onFinish'));//任务结束时执行
        $this->serv->start();

    }

    public function onWorkerStart($serv, $id) {
        var_dump("onWorkerStart");
//        $this->mDatabase = new Medoo([
//            // required
//            'database_type' => 'mysql',
//            'database_name' => DB_NAME,
//            'server' => '127.0.0.1',
//            'username' => 'root',
//            'password' => 'N!ckand3nkh33',
//
//            // [optional] Table prefix
//            'prefix' => 'weixin_'
//        ]);
    }

    public function onReceive($serv, $fd, $from_id, $data)
    {
        var_dump("receive data: ". $data);
        $data = json_decode($data, true);
        var_dump($data);
        $serv->send($fd, json_encode(array("status"=>0)));
//        $addData["mobile"] = "18888888888";
//        $addData["weixin"] = "hahaha";
//        $addData["country"] = "country";
//        $addData["device_num"] = "3";
//
//        $this->mDatabase->insert("yichong_device_apply", $addData);
        $task_id = $serv->task($data);//这里发起了任务，于是上面的on('task', array($this, 'onTask'))就会执行

    }

    public function onTask($serv, $task_id, $from_id, $data)
    {
//        $data['send_res'] = $this->sendMsg($data); //发送短信
        //1.7.3之前，是$serv->finish("result");

        $dbConfig = array("host"=> "127.0.0.1", "name"=> DB_NAME, "user"=>"root",
            "passwd"=> 'N!ckand3nkh33', "charset"=> "utf8", "type"=>1, "setname"=>true );
        $this->mDatabase = new \SQL\Database($dbConfig);
        $this->mDatabase->init();

        var_dump("on task:\n");
        var_dump($data);
        $i = 0;
        for (; $i < 20; $i++) {
            var_dump("do task");
            sleep(1);
            $checkRes = OneNet::getCommandStatus($data["cmd_uuid"]);
            var_dump($checkRes);
            if (!empty($checkRes)) {
//                $checkRes["status"] = 7;
                if ($checkRes["status"] == 4) {
                    var_dump("get ack, orderno is: " . $data["order_no"]);
                    $queryStr = sprintf(
                        "update weixin_yichong_charge set has_execute='%d' where order_no='%s'", 1, $data["order_no"]);
                    $this->mDatabase->query($queryStr);  //["cmd_uuid"=>$data["cmdUuid"]] 应该使用cmd_uuid,但由于ping++测试环境存在问题，所以暂时使用order_no
                    $this->payForVendor($data['order_no']);
                    if (!empty($data["share_order_no"]) ) {
                        $this->returnToSharer($data["order_no"], $data["share_order_no"]);
                    }
                    break;
                }
            } else {
                Util::systemErrorAlert("onTask: OneNet getCommandStatus return empty!");
                echo json_encode(array("status"=>7)); //请求失败
            }
        }

        if ($i >= 20 && empty($data["is_from_share"])) {
            $this->returnToUser($data["order_no"]);
        }

        return "result.";//这里告诉任务结束，于是上面的on('finish', array($this, 'onFinish'))就会执行
    }

    public function onFinish($serv, $task_id, $data)
    {
        var_dump("on finish");
//        $this->addSendLog($data); //添加短信发送记录
    }

    public function payForVendor($orderNo) {

        $queryStr = "select times, price, weixin_yichong_user.open_id, order_no, cmd_uuid 
                      from weixin_yichong_charge join weixin_yichong_device on weixin_yichong_device.device_id=weixin_yichong_charge.device_id 
                      join weixin_yichong_user on weixin_yichong_device.uid = weixin_yichong_user.uid 
                      where order_no='" . $orderNo . "'";
        $chargeRes = $this->mDatabase->query($queryStr)->fetchall();

        if (empty($chargeRes)) {
            Util::systemErrorAlert("payForVendor: sql query result empty");
        }

        var_dump($chargeRes);
        if (is_array($chargeRes) && count($chargeRes, COUNT_NORMAL) == 1) {
            //支付给经营者
            $times = $chargeRes[0]['times'];
            $price = $chargeRes[0]['price'];
            $amout = $times * $price * 100;
            $this->pingTransfer(WX_PUB, $chargeRes[0]['open_id'], $orderNo, '有用户使用您的"扫扫易充"智能充电站啦！', $amout);
            $updateStr = sprintf(
                "update weixin_yichong_charge set has_transfered_merchant='%d' where order_no='%s'", 1, $orderNo);
            $this->mDatabase->query($updateStr);
        }
    }

    public function returnToSharer($orderNo, $shareOrderNo) {
        $queryStr = "select * from weixin_yichong_charge 
                      join weixin_yichong_device on weixin_yichong_device.device_id=weixin_yichong_charge.device_id 
                      where order_no='" . $shareOrderNo . "'";
        $shareChargeRes = $this->mDatabase->query($queryStr)->fetchAll();
        if (empty($shareChargeRes)) {
            Util::systemErrorAlert("returnToSharer: sql query result empty!");
        }

        if (is_array($shareChargeRes) && count($shareChargeRes, COUNT_NORMAL) == 1) {
            $shareCharge = $shareChargeRes[0];

            if ($shareCharge['has_rewards'] == 0) {//如果分享单没有返现
                //返现给分享者
                $times = $shareCharge['times'];
                $price = $shareCharge['price'];
                $amout = $times * $price * 100;
                $msg = '有好友通过你的分享充电了，充电分享赢取更多"扫扫易充"返现红包哦！';
                $payRes = $this->pingTransfer(WX_PUB, $shareCharge['open_id'], $shareCharge['order_no']."1", $msg, $amout);


                $updateStr = sprintf(
                    "update weixin_yichong_charge set has_rewards='%d' where order_no='%s'", 1, $orderNo);
                $this->mDatabase->query($updateStr);

                $updateStr = sprintf(
                    "update weixin_yichong_charge set has_rewards='%d' where order_no='%s'", 1, $shareOrderNo);
                $this->mDatabase->query($updateStr);

                //TODO: 判断是否保存成功

                $selectStr = sprintf("select open_id from weixin_yichong_charge where order_no='%s'", $orderNo);
                $res = $this->mDatabase->query($selectStr)->fetchall();
                if (count($res, COUNT_NORMAL) == 1) {
                    $updateStr = sprintf(
                        "update weixin_yichong_user set has_free='%d' where open_id='%s'", 1, $res[0]['open_id']);
                    $this->mDatabase->query($updateStr);
                }
            }
        }
    }

    public function returnToUser($orderNo) {

        var_dump("return to user");
        $queryStr = "select * from weixin_yichong_charge join weixin_yichong_device on weixin_yichong_charge.device_id = weixin_yichong_device.device_id where order_no='" . $orderNo . "'";
        $chargeRes = $this->mDatabase->query($queryStr)->fetchAll();
        if (empty($chargeRes)) {
            Util::systemErrorAlert("returnToUser(退款): sql query empty!");
        }
        var_dump($chargeRes);
        if (is_array($chargeRes) && count($chargeRes, COUNT_NORMAL) == 1) {
            $times = $chargeRes[0]['times'];
            $price = $chargeRes[0]['price'];
            $amout = $times * $price * 100;
            $re = $this->pingRefund($chargeRes[0]["charge_id"], $amout);
            var_dump($re);
            var_dump($re["status"]);
            if (!empty($re)) {
                var_dump("update refund status");
                $updateStr = sprintf(
                    "update weixin_yichong_charge set refund_status='%s' where order_no='%s'", $re["status"], $orderNo);
                $this->mDatabase->query($updateStr);
            } else {
                $updateStr = sprintf(
                    "update weixin_yichong_charge set refund_status='%s' where order_no='%s'", "failed", $orderNo);
                $this->mDatabase->query($updateStr);
            }
        }

    }

    /**
     * 企业付款，暂只支持银联、微信公众号
     */
    public function pingTransfer($channel, $recipient, $orderNo, $msg, $amount=100) {

        require_once 'pingpp/init.php';
        \Pingpp\Pingpp::setPrivateKeyPath('pingpp/data/yichong.pem');
        \Pingpp\Pingpp::setApiKey(API_LIVE_KEY);
//        var_dump(APP_ID);
        // 创建 Transfer
        try {
            $tr = \Pingpp\Transfer::create(
                array(
                    'amount'    => $amount,// 订单总金额, 人民币单位：分（如订单总金额为 1 元，此处请填 100,企业付款最小发送金额为 1 元）
                    'order_no'  => $orderNo,//date('mdHis') . mt_rand(1, 9999),// 企业转账使用的商户内部订单号。wx(新渠道)、wx_pub 规定为 1 ~ 50 位不能重复的数字字母组合、unionpay 为不 1~16 位数字
                    'currency'  => 'cny',
                    'channel'   => $channel,// 目前支持 wx(新渠道)、 wx_pub、unionpay
                    'app'       => array('id' => APP_ID),
                    'type'      => 'b2c',// 付款类型，当前仅支持 b2c 企业付款。
                    'recipient' => $recipient,// 接收者 id， 为用户在 wx(新渠道)、wx_pub 下的 open_id
                    'description' => $msg,
                    'extra' => array(
                        'user_name' => '', //收款人姓名。当该参数为空，则不校验收款人姓名，选填
                        'force_check' => false// 是否强制校验收款人姓名。仅当 user_name 参数不为空时该参数生效，选填
                    )
                )
            );
//            echo $tr;// 输出 Ping++ 返回的企业付款对象 Transfer
        } catch (\Pingpp\Error\Base $e) {
            header('Status: ' . $e->getHttpStatus());
            echo($e->getHttpBody());
        }

    }

    /**
     * 企业退款
     * @param $orderNo
     * @param $amout
     * @return mixed
     */
    public function pingRefund($orderNo, $amout) {
        require_once 'pingpp/init.php';


        \Pingpp\Pingpp::setPrivateKeyPath('pingpp/data/yichong.pem');
        \Pingpp\Pingpp::setApiKey(API_LIVE_KEY);

        //创建 Batch transfer 对象
        try {
            // 通过发起一次退款请求创建一个新的 refund 对象，只能对已经发生交易并且没有全额退款的 charge 对象发起退款
            $ch = \Pingpp\Charge::retrieve($orderNo);// Charge 对象的 id
            $re = $ch->refunds->create(
                array(
                    'amount' => $amout,// 退款的金额, 单位为对应币种的最小货币单位，例如：人民币为分（如退款金额为 1 元，此处请填 100）。必须小于等于可退款金额，默认为全额退款
                    'description' => '扫扫易充退款，给您带来不便谨表歉意！'
                )
            );
//            echo $re;// 输出 Ping++ 返回的退款对象 Refund
            return $re;
        } catch (\Pingpp\Error\Base $e) {
            if ($e->getHttpStatus() != null) {
                header('Status: ' . $e->getHttpStatus());
                echo $e->getHttpBody();
            } else {
                echo $e->getMessage();
            }
        }
        exit;
    }


}

$msgServ = new msgServer();